package com.gitee.wsl.common.ui.ext.color

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.unit.Dp
import kotlin.math.ln
import kotlin.math.max


/**
 * Maximum value for RGB components.
 */
val Color.Companion.MAX_RGB: Int
    get() = 255

/**
 * Maximum value for alpha component.
 */
val Color.Companion.MAX_ALPHA: Double
    get() = 1.0


fun Color.withElevation(elevation: Dp): Color {
    val foreground = calculateForeground(elevation)
    return foreground.compositeOver(this)
}

/**
 * @return the alpha-modified [Color.White] to overlay on top of the surface color to produce
 * the resultant color.
 */
private fun calculateForeground(elevation: Dp): Color {
    val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
    return Color.White.copy(alpha = alpha)
}

inline fun Color?.takeOrElse(block: () -> Color): Color =
    if (this != null && isSpecified) this else block()

infix fun Color?.or(block:  Color): Color = takeOrElse({ block })


/** Returns the inverted version of this color. */
fun Color.inverted(): Color {
    return Color(1.0f - this.red, 1.0f - this.green, 1.0f - this.blue, this.alpha)
}

/** Returns saturated version of this color. */
fun Color.withSaturation(factor: Float): Color {
    val red = this.red
    val green = this.green
    val blue = this.blue
    if (red == green || green == blue) {
        // monochrome
        return this
    }
    val hsbvals = RGBtoHSB(this)
    var saturation = hsbvals[1]
    saturation = if (factor > 0.0) {
        saturation + factor * (1.0f - saturation)
    } else {
        saturation + factor * saturation
    }
    return HSBtoRGB(floatArrayOf(hsbvals[0], saturation, hsbvals[2])).byAlpha(this.alpha)
}

/** Returns hue-shifted (in HSB space) version of this color. */
fun Color.withHueShift(hueShift: Float): Color {
    val hsbvals = RGBtoHSB(this)
    var hue = hsbvals[0]
    hue += hueShift
    if (hue < 0.0) {
        hue += 1.0f
    }
    if (hue > 1.0) {
        hue -= 1.0f
    }
    return HSBtoRGB(floatArrayOf(hue, hsbvals[1], hsbvals[2])).byAlpha(this.alpha)
}


val Color.colorStrength: Float
    get() = max(this.colorBrightness, this.inverted().colorBrightness)







